home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / presto / presto10.lha / src / shbrk.c < prev    next >
C/C++ Source or Header  |  1991-12-11  |  7KB  |  312 lines

  1. /* $Copyright:    $
  2.  * Copyright (c) 1984, 1985, 1986 Sequent Computer Systems, Inc.
  3.  * All rights reserved
  4.  *  
  5.  * This software is furnished under a license and may be used
  6.  * only in accordance with the terms of that license and with the
  7.  * inclusion of the above copyright notice.   This software may not
  8.  * be provided or otherwise made available to, or used by, any
  9.  * other person.  No title to or ownership of the software is
  10.  * hereby transferred.
  11.  */
  12.  
  13. #ifndef    lint
  14. static    char    rcsid[] = "$Header: shbrk.c 1.3 88/03/31 $";
  15. #endif
  16.  
  17. /*
  18.  * shbrk.c
  19.  *    Parallel run-time basic shared memory allocator.
  20.  *
  21.  * Heavily based on Sequent parallel programming library shared memory
  22.  * manager.  Greatly simplified.
  23.  */
  24.  
  25. /* $Log:    shbrk.c,v $
  26.  * Revision 1.3  88/03/31  15:39:43  rbk
  27.  * Drop all refs to "do_shared_stack" (not necessary, and value was 0).
  28.  * Also drop all refs to _single_stack -- not needed, since signal handling
  29.  * much simpler than microtasking code (child processes don't trap signals).
  30.  * _init_shstk() is now a NOP since not using the microtasking library's
  31.  * "shared stack"; drop other junk dealing with this shared stack
  32.  * (misc #define's, variables, grow_stack()).
  33.  * Other simplifications for simpler environment.
  34.  * 
  35.  * Revision 1.2  88/03/24  09:52:32  rbk
  36.  * Import MMAP macro, drop #include of parc.h.  Also #unifdef -DCONCAT.
  37.  * 
  38.  * Revision 1.1  88/03/22  15:23:28  rbk
  39.  * Initial revision
  40.  * 
  41.  */
  42.  
  43. #ifdef sequent
  44.  
  45. #include <sys/types.h>
  46. #include <sys/errno.h>
  47. #include <sys/file.h>
  48. /*#include <stddef.h>*/
  49. #include <sys/mman.h>
  50. #include <sys/signal.h> 
  51. #include <parallel/parallel.h>
  52.  
  53. #define    MMAP(fd,va,sz,pos)    \
  54.         mmap(va, sz, PROT_READ|PROT_WRITE, MAP_SHARED, fd, pos)
  55.  
  56. /*
  57.  * Module local variables.
  58.  */
  59.  
  60. private    int    priv_stack_limit;        /* size limit for priv stack */
  61. private    static    char    *myshbrk;        /* process local max sbrk */
  62. shared    static    char    *curshbrk;        /* global for all processes */
  63. shared    static    slock_t    shbrk_lock = L_UNLOCKED;
  64.  
  65. /*
  66.  * _init_shbrk()
  67.  *    Initialize basic shared-memory allocator.
  68.  *
  69.  * Called from _ppinit().
  70.  *
  71.  * Since the memory manager comes into play on a SEGV signal, we have to be
  72.  * careful that we don't get preempted at any point from within this handler,
  73.  * since the "state" represented by the fp and sp are transient.  This routine
  74.  * must be allowed to finish without interruption.
  75.  *
  76.  * We also block the SIGUSR1 and SIGVTALRM signals (SIGUSR1 and SIGVTALRM
  77.  * are used by preemption code).
  78.  */
  79.  
  80. static int    segvh();
  81.  
  82. static struct sigvec vec =  {
  83.     segvh, 
  84.     sigmask(SIGSEGV)|sigmask(SIGCHLD)|sigmask(SIGUSR1)|sigmask(SIGVTALRM),
  85.     1
  86. };
  87.  
  88. extern    void    enable_interrupts();
  89. extern    int    disable_interrupts();
  90.  
  91. static    private    int    reenable_interrupts = 0;
  92.  
  93. #define DISABLE_INTERRUPTS()  {reenable_interrupts = disable_interrupts();}
  94. #define ENABLE_INTERRUPTS()   {if (reenable_interrupts) enable_interrupts();}
  95.  
  96. private    static    int    segvstack[512];
  97. private    static    struct    sigstack sigstruct = {(caddr_t)&segvstack[511], 0};
  98.  
  99. int    sigstack();
  100. char    *getenv();
  101.  
  102. /*
  103. _check_segv()
  104. {
  105. }
  106. */
  107.  
  108. _init_shbrk()
  109. {
  110.     extern    shared char _shend_;
  111.  
  112.     /*
  113.      * Set up SIGSEGV handler; catch signal and grow shared-data
  114.      * and shared stack if appropriate.
  115.      */
  116.  
  117.     (void) sigstack(&sigstruct, (struct sigstack *)0);
  118.     (void) sigvec(SIGSEGV, &vec, (struct sigvec *)0);
  119.  
  120.     /*
  121.      * Initialize state variables.
  122.      */
  123.  
  124.     curshbrk = myshbrk = &_shend_;
  125.     return(0);
  126. }
  127.  
  128. /*
  129.  * shsbrk()
  130.  *    shared-memory sbrk(); create new shared space, return start address.
  131.  */
  132.  
  133. char *
  134. shsbrk(incr)
  135.     int    incr;
  136. {
  137.     register slock_t *spin_ptr = &shbrk_lock;
  138.     char    *val;
  139.  
  140.     if (incr == 0)
  141.         return(curshbrk);    /* note: can race with others! */
  142.  
  143.     if (incr < 0) {            /* can't shrink */
  144.         errno = EINVAL;
  145.         return((char *) -1);
  146.     }
  147.  
  148.     /*
  149.      * Lock data-file to insure one shared-brk at a time (and
  150.      * stable value of curshbrk).
  151.      */
  152.  
  153.     DISABLE_INTERRUPTS();
  154.     S_LOCK(spin_ptr);
  155.  
  156.     val = curshbrk;
  157.     if (lshbrk(val + incr) < 0)
  158.         val = (char *) -1;
  159.  
  160.     S_UNLOCK(spin_ptr);
  161.     ENABLE_INTERRUPTS();    
  162.     return(val);
  163. }
  164.  
  165. /*
  166.  * shbrk()
  167.  *    Add shared address space, analogous to brk().
  168.  *
  169.  * Just front-end to lshbrk() -- lock file and try to grow.
  170.  */
  171.  
  172. shbrk(newbrk)
  173.     char    *newbrk;
  174. {
  175.     register slock_t *spin_ptr = &shbrk_lock;
  176.     int    val;
  177.  
  178.     DISABLE_INTERRUPTS();
  179.     S_LOCK(spin_ptr);
  180.  
  181.     val = lshbrk(newbrk);
  182.  
  183.     S_UNLOCK(spin_ptr);
  184.     ENABLE_INTERRUPTS();
  185.     return(val);
  186. }
  187.  
  188. /*
  189.  * lshbrk()
  190.  *    "Locked" shbrk().  Internal procedure.
  191.  *
  192.  * Assumes caller locked shmem file, to serialize access to this code.
  193.  * No need to check if running into bottom of UNIX private stack since
  194.  * threads run on their own stacks.
  195.  */
  196.  
  197. static
  198. lshbrk(newbrk)
  199.     register char    *newbrk;
  200. {
  201.     register char    *cur;            /* actual brk (rounded) */
  202.     register char    *new;            /* requested brk (rounded) */
  203.     extern    shared char    _shstart_;    /* start of shared stuff */
  204.  
  205.     /*
  206.      * Not allowed to shrink self (yet).
  207.      */
  208.  
  209.     if (newbrk < myshbrk) {
  210.         errno = EINVAL;
  211.         return(-1);
  212.     }
  213.  
  214.     /*
  215.      * Growing: if no actual increase (rounding/etc), just adjust
  216.      * (self) myshbrk.
  217.      */
  218.  
  219.     cur = PGRND(myshbrk);
  220.     if (cur >= newbrk) {
  221.         myshbrk = newbrk;
  222.         if (newbrk > curshbrk)
  223.             curshbrk = myshbrk;
  224.         return(0);
  225.     }
  226.     new = PGRND(newbrk);
  227.  
  228.     /*
  229.      * Need to mmap() more of file.
  230.      */
  231.  
  232.     if (MMAP(_shm_fd, cur, new - cur, cur - &_shstart_) < 0) {
  233.         errno = ENOMEM;
  234.         return(-1);
  235.     }
  236.  
  237.     myshbrk = newbrk;        /* maybe not aligned */
  238.     if (newbrk > curshbrk)
  239.         curshbrk = newbrk;    /* grew the global memory */
  240.  
  241.     return(0);            /* success! */
  242. }
  243.  
  244. /*
  245.  * _init_shstk()
  246.  *    Initialize microtasking shared-stack.
  247.  *
  248.  * Called from _ppinit().
  249.  */
  250.  
  251. int *
  252. _init_shstk(ctxt_bottom, ctxt_top)
  253.     int    *ctxt_bottom;
  254.     int    *ctxt_top;
  255. {
  256.     /*
  257.      * NOP -- never called since not using "microtask shared stack".
  258.      */
  259.     return(0);
  260. }
  261.  
  262. /*
  263.  * segvh()
  264.  *    SIGSEGV handler.
  265.  *
  266.  * If process isn't up to max shared-data, get there and re-try the
  267.  * instruction.  Else turn off handler and retry (==> dump core).
  268.  */
  269.  
  270. /*ARGSUSED*/
  271. static
  272. segvh(sig, code, scp)
  273.     int sig, code;
  274.     struct sigcontext *scp;
  275. {
  276.     register slock_t *spin_ptr = &shbrk_lock;
  277.     register int *fa = (int *)code;
  278.  
  279.     /*
  280.      * A signal code of -1 indicates the signal originated from a
  281.      * kill() system call, rather than a real program fault.
  282.      */
  283.  
  284.     if (fa == (int *)-1) {
  285.         (void) signal(SIGSEGV, SIG_DFL);
  286.         (void) kill(getpid(), SIGSEGV);
  287.         return;
  288.     }
  289.  
  290.     /*
  291.      * If process doesn't have all of shared heap mapped, map it and retry.
  292.      * Otherwise turn off SIGSEGV handling.
  293.      *
  294.      * Lock data-file during this to stabilize curshbrk and
  295.      * insure only one lshbrk() at a time.
  296.      *
  297.      * Return retries instruction, will die for real if turn off
  298.      * signal handling here.
  299.      */
  300.  
  301.     DISABLE_INTERRUPTS();
  302.     S_LOCK(spin_ptr);
  303.  
  304.     if (myshbrk >= curshbrk || lshbrk(curshbrk) < 0)
  305.         (void) signal(SIGSEGV, SIG_DFL);
  306.  
  307.     S_UNLOCK(spin_ptr);
  308.     ENABLE_INTERRUPTS();
  309. }
  310.  
  311. #endif /* sequent */
  312.